# File: menu1.py
#Final working Routing Algorithm with link weight changes and node clicks 
from pylab import* 
class Node():
	def __init__(self,nbors,nbors1,myname):
        	self.nbrs=nbors1
		self.myname=myname
		self.routing_table=nbors
		self.next_hop_table={}	
		for i in self.nbrs.keys():
			self.next_hop_table[i]=i	
		
    	def routing_algorithm(self,all_nodes):
		
        	#self.routing_table=self.nbrs
        	for i in self.routing_table.keys():
            		#nb=eval(i)
			nb=all_nodes[i]
            		nb_nb=nb.routing_table
            		for j in nb_nb:
                		if j!=self.myname:
                   			if not(j in self.routing_table.keys()):
                        			self.routing_table[j]=nb_nb[j]+self.routing_table[i]
						if i in self.nbrs.keys():
							self.next_hop_table[j]=i
						else:
							self.next_hop_table[j]=self.next_hop_table[i]
                    			if (j in self.routing_table.keys()):
                        			temp=nb_nb[j]+self.routing_table[i]
                        			c=self.routing_table[j]
                        			if temp<c:
                            				self.routing_table[j]=temp
							if i in self.nbrs.keys():
								self.next_hop_table[j]=i
							else:
								self.next_hop_table[j]=self.next_hop_table[i]
				#if j==self.myname:
				#	if self.routing_table[i]>nb_nb[j]:
				#		self.routing_table[i]=nb_nb[j]
				#		k=nb.next_hop_table[j]
				#		while k not in self.nbrs.keys():
				#			k=all_nodes[k].next_hop_table[j]
				#		self.next_hop_table[i]=k
		#self.nbrs=self.routing_table

class initial_topo():
	def __init__(self):
		self.topology={}

	def complete_topo(self,neighbours,myname):
		self.topology[myname]=neighbours
		
	def get_topology(self):
		return self.topology


import Tkinter, Tkconstants, tkFileDialog, tkMessageBox,tkSimpleDialog
class TkFileDialogExample():
	def __init__(self):
		#Tkinter.Frame.__init__(self,root)
		#self.root1=root1
		#frame=Tkinter.Frame(self.root1,width=10000, height=10000)
		#self.button_opt={'fill': Tkconstants.BOTH, 'padx': 5, 'pady': 5}
		self.all_nodes={}
	       	#Tkinter.Button(frame,text='askopenfilename', command=self.askopenfilename).pack(**self.button_opt)
		#frame.pack()
		self.file_opt=options={}
		options['defaultextension']=''
		options['filetypes']=[('text files', '.txt')]
		self.askopenfilename()
	
	

	def askopenfilename(self):
		filename=tkFileDialog.askopenfilename(**self.file_opt)
		a=[str(filename)]
		print a
		filename
		if filename=='':
			#self.root1.destroy()
			pass
		else:
			if filename:
				T=initial_topo()
				for i in open(filename):
					node_nbr=i.split(':')
					nbr_str=node_nbr[1]
					nbr_lst=nbr_str.split()
					neighbours={}
					neighbours1={}
					for j in range(len(nbr_lst)):
						if j%2==0:
							neighbours[nbr_lst[j]]=int(nbr_lst[j+1])
							neighbours1[nbr_lst[j]]=int(nbr_lst[j+1])
					self.all_nodes[node_nbr[0]]=Node(neighbours,neighbours1,node_nbr[0])
					#print "MAm"
					#print self.all_nodes[node_nbr[0]].my_nbrs
			#self.update_routing()
			#print self.all_nodes
			#self.root1.destroy()
			root2=Tk()
			root2.title("Network Simulator - Import Network")
			C=Display_network(root2,self.all_nodes)
			root2.mainloop()


class Display_table():
	def __init__(self,A,tag_node,C):
		self.A=A
		self.this_node_name=tag_node
		self.C=C
	def show_table(self):
		#string="This node is "+self.this_node_name
		#tkMessageBox.showinfo('Routing Table', string)
		k=''
		k=k+self.this_node_name
		this_node_instance=self.A[k]
		this_node_instance.routing_algorithm(self.A)
		print this_node_instance.nbrs
		#print this_node_instance.routing_table
		#string= string+'\n'+str(this_node_instance.routing_table)+'\n'+str(this_node_instance.next_hop_table)
		#string= string+'\n'+str(this_node_instance.my_nbrs)
		#tkMessageBox.showinfo('Routing Table', string,parent=self.C)
		stri='\n' + "This node is "+self.this_node_name	
		stri=stri+'\n'+'Node'+'\t'+'Cost'+'\t'+'Next hop'
		for node in this_node_instance.routing_table.keys():
			stri =stri + '\n'+str(node) + '\t' + str(this_node_instance.routing_table[node]) + '\t' + str(this_node_instance.next_hop_table[node])
		tkMessageBox.showinfo('Routing Table', stri,parent=self.C)	
	
class change_link():
	def __init__(self,A,link_nodes,C):
		self.A=A
		self.link_nodes=link_nodes
		self.C=C
	def link_info(self):
		string="My nodes are "+str(self.link_nodes)
		#tkMessageBox.showinfo('Routing Table', string)
		#tkMessageBox.showinfo('Link Information', string)
		prsnt_wt=self.A[self.link_nodes[0]].nbrs[self.link_nodes[1]]
		string=string+'\n'+'Present cost = '+ str(prsnt_wt)+'\n'+'Change cost'
		weight=tkSimpleDialog.askfloat("Link Information",string,parent=self.C)
		if weight!=None:
			for k in self.A.keys():
				self.A[k].routing_table={}
				for j in self.A[k].nbrs.keys():
					temp=self.A[k].nbrs[j]
					self.A[k].routing_table[j]=temp
				

			link_n1=self.A[self.link_nodes[0]]
			link_n2=self.A[self.link_nodes[1]]
			link_n1.routing_table[self.link_nodes[1]]=weight
			link_n1.nbrs[self.link_nodes[1]]=weight
			link_n2.routing_table[self.link_nodes[0]]=weight
			link_n2.nbrs[self.link_nodes[0]]=weight
			#link_n1.routing_algorithm(self.A)
			#link_n2.routing_algorithm(self.A)
		if weight==None:
			pass

			
def update_routing(A):
                for k in A.keys():
                        a_node=A[k]
                        a_node.routing_algorithm(A)
		for k in A.keys():
                        a_node=A[k]
                        a_node.routing_algorithm(A)
                for k in A.keys():
                        a_node=A[k]
                        #print a_node.routing_table
	
class Display_network():
	def __init__(self,root2,A):
		self.A=A
		#self.master2=master2
		self.frame = Frame(root2,width=100, height=100)
		self.frame.pack()
		self.show_network()

	def show_network(self):
		#tkMessageBox.showinfo('Routing Table', "Table is")
		w = Canvas(self.frame, width=500, height=500,bg='white',bd=1,relief='raised')
		w.pack()
		print self.A.keys()
		#w.create_rectangle(50, 25, 150, 75, fill="blue")
		s=20 
		node_tag={}
		node_pos={}
		o_x,o_y=250,250
		r=125
		length=0
		for k in self.A.keys():
			length=length+1
		theta=(2*pi)/length
		increment=(2*pi)/length
		for k in self.A.keys():
			#print k
			#node=w.create_oval(s+30,s+30,s+40,s+40,fill='red', activefill='green', tags=k)
			x_cor=o_x+r*cos(theta)
			y_cor=o_y+r*sin(theta)
			node=w.create_oval(x_cor,y_cor,x_cor+10,y_cor+10,fill='red', activefill='green', tags=k)
			nit=(node+1)/2
			nodetag='n'+"%s" %nit
			w.create_text(x_cor+5,y_cor-5,fill="black",text=nodetag,font=("Helvetica","7","italic"))
			node_tag[k]=node
			w.tag_bind(node, "<Button-1>", lambda x:node_click(w,self.A))
			node_pos[k]=[x_cor+10,y_cor+10] 
                        theta=theta+increment

		for k in self.A.keys():
			a_node=self.A[k]
			RT=a_node.nbrs
			for n in RT.keys():
				line=w.create_line(node_pos[k][0], node_pos[k][1], node_pos[n][0], node_pos[n][1], fill="blue",activefill='red')
				#line=w.create_line(node_pos[k][0], node_pos[k][1], node_pos[n][0], node_pos[n][1], fill="blue",width=2.0,activefill='red')
				w.tag_bind(line, "<Button-1>", lambda x:line_click(w,self.A))				
			
			
#if __name__=='__main__':
#	root=Tkinter.Tk()
#	Network=TkFileDialogExample(root)
#	root.mainloop()
#	A=Network.all_nodes
#	update_routing(A)
	
from Tkinter import *

def callback():
	print "Open Canvas to create Network!"
def Open():
	#root1=Tk()
	Network=TkFileDialogExample()
	#root1.mainloop()
	A=Network.all_nodes
	#pdate_routing(A)
	#print A.all_nodes[node_nbr[0]].my_nbrs
	#tkMessageBox.showinfo('R Table', "Table here",)
	#root.mainloop()	
	#root2=Tk()
	#C=Display_network(root2,A)
	#update_routing(A)
	#root2.mainloop()

def h_importNtw():
	print "Snapshots to create Network!"
	master = Tk()
	master.title("Help - Import Network")
	master.config(bg='white')
	for line in open('Help1.txt'):
		w = Label(master, text=line,bg='white')
		w.pack()
def h_createNtw():
	print "Snapshots to create Network!"
	master = Tk()
	master.title("Help - Create Network")
	master.config(bg='white')
	for line in open('help2.txt'):
		w = Label(master, text=line,bg='white')
		w.pack()

#############################################################################################################################
from Tkinter import *
import Tkconstants
def create_net():

	class create_Ntw():
		def __init__(self):
			self.node_count=0
			self.node_listM=[]
			self.link_listM=[]
			self.net_topo={}
			self.all_nodes={}
			#self.root3 = Tk()
			self.root3 = Toplevel()
			self.root3.title("Network Simulator - Create Network")
			self.root3.columnconfigure(0, weight=1)
			self.root3.rowconfigure(0, weight=1)
			self.frame1 = Frame(self.root3,width=700, height=700,bg='blue')
			self.frame1.pack()
			self.create()

		def xy(self,event):
			
  	        	self.lastx, self.lasty = event.x, event.y
			self.node_count+=1
			nodetag='n'+"%s" %self.node_count
			self.node_listM.append(nodetag)
			print self.node_listM
			self.canvas.create_oval(self.lastx,self.lasty,self.lastx+10,self.lasty+10,fill='red', activefill='green',tags=nodetag)
			#self.canvas.insert(nodetag, INSERT, "h")
			self.canvas.create_text(self.lastx+5,self.lasty-5,fill="black",text=nodetag,font=("Helvetica","7","italic"))
			self.net_topo[nodetag]={}
			print self.net_topo
			
		def Node_insert(self):
			sim=0
			self.b1.config(relief=SUNKEN)
			self.b2.config(relief=RAISED)
			self.b3.config(relief=RAISED)
			self.canvas.unbind("<Double-Button-1>")
			self.canvas.bind("<Button-1>", self.xy)

		def addLine_start(self,n):
			n=self.canvas.find_withtag(CURRENT)[0]
			print self.canvas.coords(n)
			self.n_tag_s=self.canvas.gettags(n)[0]
			print self.n_tag_s
			self.lastx_s=self.canvas.coords(n)[0]
			self.lasty_s=self.canvas.coords(n)[1]
			print "St"
			print self.lastx_s,self.lasty_s
			for m in self.node_listM:
				nod=self.canvas.find_withtag(m)[0]
				self.canvas.tag_unbind(m, "<Double-Button-1>")
			for m in self.node_listM:
				self.canvas.tag_bind(m, "<Button-1>", lambda x:self.addLine_end(n))
			

		def addLine_end(self,n):
			n=self.canvas.find_withtag(CURRENT)[0]
			self.n_tag_e=self.canvas.gettags(n)[0]
			print self.n_tag_e
			if self.n_tag_s != self.n_tag_e:
				if self.n_tag_e not in self.net_topo[self.n_tag_s]:
					self.net_topo[self.n_tag_s][self.n_tag_e]=None
				if self.n_tag_s not in self.net_topo[self.n_tag_e]:
					self.net_topo[self.n_tag_e][self.n_tag_s]=None
			print self.net_topo
			print self.canvas.coords(n)
			self.lastx_e=self.canvas.coords(n)[0]
			self.lasty_e=self.canvas.coords(n)[1]
			print "en"
			print self.lastx_e,self.lasty_e
   			line_c=self.canvas.create_line((self.lastx_s, self.lasty_s, self.lastx_e, self.lasty_e),fill="blue",activefill='red')
			self.canvas.tag_bind(line_c, "<Button-1>", lambda x:self.line_c_click(line_c))
			line_tag='l'+'%s' %line_c
			self.canvas.addtag_withtag(line_tag,line_c)
			self.link_listM.append(line_tag)
			#line_tag_display=(line_c-2*len(self.node_listM)+1)/2
			#line_tag_display='l'+'%s' %line_tag_display
			#self.canvas.addtag_withtag(line_tag_display,line_c)
			#po1=(self.lastx_s+self.lastx_e)/2
			#po2=(self.lasty_s+self.lasty_e)/2 -5
			#self.canvas.create_text(po1,po2,fill="black",text=line_tag_display,font=("Helvetica","7","italic"))
			for m in self.node_listM:
				nod=self.canvas.find_withtag(m)[0]
				self.canvas.tag_unbind(m, "<Button-1>")
			for m in self.node_listM:
				self.canvas.tag_bind(n, "<Double-Button-1>", lambda x:self.addLine_start(n))

		def line_c_click(self,l):
			if self.sim==0:
				try:    
					print "call to line_c_click"
					print self.canvas.find_withtag(CURRENT)
					l=self.canvas.find_withtag(CURRENT)[0]	
					#line_tag='l'+'%s' %l
					#self.canvas.addtag_withtag(line_tag,l)
					print self.canvas.gettags(l)
					#line_tag=self.canvas.gettags(l)[1]
					#self.link_listM.append(line_tag)
					ln_1x=self.canvas.coords(l)[0]
					ln_1y=self.canvas.coords(l)[1]
					ln_2x=self.canvas.coords(l)[2]
					ln_2y=self.canvas.coords(l)[3]
					print self.canvas.find_overlapping(ln_1x-5, ln_1y-5,ln_1x+10, ln_1y+10)
					n1=self.canvas.find_overlapping(ln_1x-5, ln_1y-5,ln_1x+10, ln_1y+10)[0]
					n2=self.canvas.find_overlapping(ln_2x-5, ln_2y-5,ln_2x+10, ln_2y+10)[0]
					n1_tag=self.canvas.gettags(n1)[0]
					n2_tag=self.canvas.gettags(n2)[0]
					string="My nodes are %s and %s" %(n1_tag,n2_tag)
					weight=tkSimpleDialog.askfloat("Link Information","change cost"+'\n'+string,parent=self.root3)
					self.net_topo[n1_tag][n2_tag]=weight
					self.net_topo[n2_tag][n1_tag]=weight
					print self.net_topo
				except IndexError:
					print "Ignore index error"
			
		
		def Link_insert(self):
			self.sim=0
			self.b2.config(relief=SUNKEN)
			self.b1.config(relief=RAISED)
			self.b3.config(relief=RAISED)
			self.canvas.unbind("<Button-1>")
			for m in self.node_listM:
				self.canvas.tag_unbind(m, "<Button-1>")
				self.canvas.tag_unbind(m, "<Double-Button-1>")
			for m in self.link_listM:
				self.canvas.tag_unbind(m, "<Double-Button-1>")
				self.canvas.tag_unbind(m, "<Button-1>")
				self.canvas.tag_bind(m, "<Button-1>", lambda x:self.line_c_click(m))
			for n in self.node_listM:
				nod=self.canvas.find_withtag(n)
				self.canvas.tag_bind(nod, "<Double-Button-1>", lambda x:self.addLine_start(n))

		def Simulate(self):
			self.sim=1
			self.b3.config(relief=SUNKEN)
			self.b1.config(relief=RAISED)
			self.b2.config(relief=RAISED)
			for m in self.link_listM:
				self.canvas.tag_unbind(m, "<Double-Button-1>")
				self.canvas.tag_unbind(m, "<Button-1>")
			for m in self.node_listM:
				self.canvas.tag_unbind(m, "<Button-1>")
			left_out=[]
			for f in self.net_topo.keys():
				for g in self.net_topo[f].keys():
					if self.net_topo[f][g] ==None:
						if set([f,g]) not in left_out:
							left_out.append(set([f,g]))
							tkMessageBox.showinfo('Warning', 'Insert cost for link between %s and %s click LINK INSERT' %(f,g),parent=self.root3)
							for m in self.link_listM:
								self.canvas.tag_unbind(m, "<Button-1>")
							for m in self.link_listM:
								self.canvas.tag_unbind(m, "<Button-1>")

						if set([f,g]) in left_out:
							pass
			for nd in self.net_topo.keys():
				neighbours1={}
				for i in self.net_topo[nd].keys():
					neighbours1[i]=self.net_topo[nd][i]
				self.all_nodes[nd]=Node(self.net_topo[nd],neighbours1,nd)
			print self.node_listM
			print self.link_listM
			for m in self.node_listM:
				self.canvas.tag_bind(m, "<Button-1>", lambda x:node_click(self.canvas,self.all_nodes))
			for m in self.link_listM:
				self.canvas.tag_bind(m, "<Button-1>", lambda x:LINE_clickM(self.canvas,self.all_nodes))
				
		def create(self):
			button_opt1={'fill': Tkconstants.BOTH, 'padx': 5, 'pady': 5,'side':LEFT}
			im=PhotoImage(file = 'C1.gif')
			self.b1=Button(self.frame1,compound=LEFT,text='Insert Node', command=self.Node_insert,image=im)
			self.b1.pack(**button_opt1)
			self.b2=Button(self.frame1,text='Insert Link', command=self.Link_insert)
			self.b2.pack(**button_opt1)
			self.b3=Button(self.frame1,text='Simulate', command=self.Simulate)
			self.b3.pack(**button_opt1)
			#b3.config(relief=SUNKEN)
			#b3.pack(**button_opt1)
			#self.canvas = Canvas(self.frame1,width=700, height=700)
			self.canvas = Canvas(self.root3,width=700, height=700,bg='white',bd=1,relief='raised',highlightcolor='blue')
			self.canvas.pack()
			self.root3.mainloop()

	Cr=create_Ntw()

################################################################################################################################	
def node_click(C,A):
	id_node=C.find_withtag(CURRENT)[0]
	tag_node=C.gettags(id_node)[0]
	#update_routing(A)
	B=Display_table(A,tag_node,C)
	B.show_table()

def line_click(C,A):
	id_line=C.find_withtag(CURRENT)[0]
	#tag_node=C.gettags(id_node)[0]
	#update_routing(A)
	posi=C.coords(id_line) 
	n1=C.find_overlapping(posi[0]-10,posi[1]-10,posi[0]+10,posi[1]+10,)[0]
	n2=C.find_overlapping(posi[2]-10,posi[3]-10,posi[2]+10,posi[3]+10,)[0]
	print n1
	print n2
	print C.gettags(n1)
	print C.gettags(n2)
	n1_tag=C.gettags(n1)[0]
	n2_tag=C.gettags(n2)[0]	
	B=change_link(A,[n1_tag,n2_tag],C)
	B.link_info()

def LINE_clickM(C,A):
	print "call to LINE_clickM"
	print C.find_withtag(CURRENT)
	id_line=C.find_withtag(CURRENT)[0]
	#tag_node=C.gettags(id_node)[0]
	#update_routing(A)
	posi=C.coords(id_line) 
	n1=C.find_overlapping(posi[0]-5,posi[1]-5,posi[0]+10,posi[1]+10)[0]
	n2=C.find_overlapping(posi[2]-5,posi[3]-5,posi[2]+10,posi[3]+10)[0]
	n1_tag=C.gettags(n1)[0]
	n2_tag=C.gettags(n2)[0]	
	B=change_link(A,[n1_tag,n2_tag],C)
	B.link_info()
	
global root
root = Tk()
root.title("Network Simulator")
# create a menu
menu = Menu(root)
root.config(menu=menu)
orig = Canvas(root, width=1500, height=800)
orig.pack()
gif1=PhotoImage(file = 'Network5.gif')
orig.create_image(50, 10, image = gif1, anchor = NW)
orig.create_text(250,50,fill="red",text="NETWORK SIMULATOR",font=("Helvetica","16","italic"))
filemenu = Menu(menu)
menu.add_cascade(label="Networks", menu=filemenu)
filemenu.add_command(label="Create a new Network", command=create_net)
filemenu.add_command(label="Import a Network", command=Open)
filemenu.add_separator()
filemenu.add_command(label="Exit", command=callback)

helpmenu = Menu(menu)
menu.add_cascade(label="Help", menu=helpmenu)
helpmenu.add_command(label="How to Import Network", command=h_importNtw)
helpmenu.add_command(label="How to Create Network", command=h_createNtw)
#w = Canvas(root, width=500, height=500)
#w.config(scrollregion=w.bbox(ALL))
#w.pack()

#w.create_line(0, 0, 200, 100)
#w.create_line(0, 100, 200, 0, fill="red", dash=(4, 4))

#w.create_rectangle(50, 25, 150, 75, fill="blue")
#node=w.create_oval(50,50,60,60,fill='red', activefill='green', tags='n1')
#w.tag_bind(node, "<Button-1>", lambda x:node_click(node))
root.mainloop()

